﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Windows.Devices.Enumeration.Pnp;
using Windows.UI;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;

namespace DT.GoogleAnalytics.Metro
{
    public static class AnalyticsHelper
    {
        public enum CustomVarKind
        {
            Visitor = 1,
            Session = 2,
            Page = 3
        }

        private static HostControl _gaJsControl = null;
        private static readonly object _actionsLock = new object();
        private static readonly List<string> _actionsToRun = new List<string>();
        private static bool _canRunEvents = false;
        private static bool _controlHostInitialized = false;
        private static string _trackingId = null;
        private static bool _enableModelTracking = true;

        private const string eventTrackingCodeWithValue = "window.PageTracker._trackEvent('{0}', '{1}', '{2}', {3});";
        private const string eventTrackingCodeWithEventName = "window.PageTracker._trackEvent('{0}', '{1}', '{2}');";
        private const string eventTrackingCodeBasic = "window.PageTracker._trackEvent('{0}', '{1}');";

        private const string customVariablesTracking = "window.PageTracker._setCustomVar({0}, '{1}','{2}',{3});";

        internal static void OnInitialized()
        {
            lock (_actionsLock)
            {
                if (_actionsToRun.Count > 0)
                {
                    foreach (var js in _actionsToRun)
                    {
                        RunJavascriptOrQueue(js, force: true);
                    }
                    _actionsToRun.Clear();
                }
            }
            _canRunEvents = true;
            if (_enableModelTracking)
            {
                RunDeviceIdentificationCode();
            }
        }

        private const string PNPPropertyModel = "System.Devices.ModelName";
        private const string PNPPropertyManufacturer = "System.Devices.Manufacturer";

        internal static void SetModelTrackingEnabled(bool value)
        {
            _enableModelTracking = value;
        }

        private static async void RunDeviceIdentificationCode()
        {
            try
            {
                string[] properties = { PNPPropertyModel, PNPPropertyManufacturer };
                var rootContainer = await PnpObject.CreateFromIdAsync(PnpObjectType.DeviceContainer, "{00000000-0000-0000-FFFF-FFFFFFFFFFFF}", properties);
                string modelName = (string)rootContainer.Properties[PNPPropertyModel];
                string manufacturer = (string)rootContainer.Properties[PNPPropertyManufacturer];
                var fullName = manufacturer + " " + modelName;
                if (!string.IsNullOrWhiteSpace(modelName))
                {
                    SetCustomVariable(1, "IsCustomDevice", "No", CustomVarKind.Session);
                    SetCustomVariable(2, "DeviceManufacturer", manufacturer, CustomVarKind.Session);
                    SetCustomVariable(3, "DeviceModel", modelName, CustomVarKind.Session);
                    SetCustomVariable(4, "DeviceFullName", fullName, CustomVarKind.Session);
                }
                else
                {
                    SetCustomVariable(1, "IsCustomDevice", "Yes", CustomVarKind.Session);
                    //тогда это кастомный комп, не ноутбук - короче не модельный представитель
                }
                //надо послать событие либо pageview - pageview "гадит" в realtime статистику
                //TrackPageView("/Analytics.DeviceModels.fakepage");
                Track("Analytics", "DeviceModels", fullName);
            }
            catch (Exception)
            {

            }
            //Track("Devices");
        }

        private static void RunJavascriptOrQueue(string fullJsCode, bool force = false)
        {
            if (_canRunEvents || force)
            {
                if (_gaJsControl != null)
                {
                    _gaJsControl.RunAnalyticsJsCode(fullJsCode);
                }
            }
            else
            {
                lock (_actionsLock)
                {
                    _actionsToRun.Add(fullJsCode);
                }
            }
        }

        private static void RegisterGaJsControl(HostControl control)
        {
            _gaJsControl = control;
            OnInitialized();
        }

        private static string ReplaceIllegalCharacters(string value)
        {
            if (string.IsNullOrWhiteSpace(value))
                return null;

            value = Regex.Replace(value, "\r\n", "[rn]");
            value = value.Replace(@"\", @"\\").Replace(@"'", @"\'").Replace("[rn]", "\\r\\n");
            return value;
        }

        internal static void SetTrackingId(string value)
        {
            _trackingId = value;
        }

        #region Public interface
        /// <summary>
        /// Sets custom variable. Value of the variable is sent with next event or pageview
        /// </summary>
        /// <param name="index">index of custom variable, &gt;0</param>
        /// <param name="name">name of custom variable</param>
        /// <param name="value">value of custom variable</param>
        /// <param name="kind">Kind of variable (per visitor, per session, per pageview)</param>
        public static void SetCustomVariable(ushort index, string name, string value, CustomVarKind kind = CustomVarKind.Session)
        {
            var js = string.Format(customVariablesTracking, index, name, value, (int)kind);
            RunJavascriptOrQueue(js);
        }

        /// <summary>
        /// Tracks event
        /// </summary>
        /// <param name="category">Event category</param>
        /// <param name="action">Event action</param>
        /// <param name="label">Event label</param>
        /// <param name="value"></param>
        public static void Track(string category, string action, string label = null, int? value = null)
        {
            category = ReplaceIllegalCharacters(category);
            action = ReplaceIllegalCharacters(action);
            label = ReplaceIllegalCharacters(label);
            string gaJsCode = null;
            if (value != null && label != null)
            {
                gaJsCode = string.Format(eventTrackingCodeWithValue, category, action, label, value);
            }
            else if (label != null)
            {
                gaJsCode = string.Format(eventTrackingCodeWithEventName, category, action, label);
            }
            else
            {
                gaJsCode = string.Format(eventTrackingCodeBasic, category, action);
            }
            string fullJsCode = @"
try{
" + gaJsCode +
                                @"
window.external.notify('event track sucess');
}
catch(e){
window.external.notify('event track failed: '+e);
}
";
            RunJavascriptOrQueue(fullJsCode);
        }

       

        /// <summary>
        /// Tracks page view
        /// </summary>
        /// <param name="pageName">Page url or name</param>
        public static void TrackPageView(string pageName)
        {
            pageName = ReplaceIllegalCharacters(pageName);
            string fullJsCode = @"
try{
window.PageTracker._trackPageview('" + pageName + @"');
window.external.notify('pageview track sucess');
}
catch(e){
window.external.notify('pageview track failed: '+e);

}";
            RunJavascriptOrQueue(fullJsCode);
        }

        /// <summary>
        /// Call this method in every place you call Window.Current.Activate(), just before that Activate()
        /// Initializes host control and google analytics infrastructure
        /// </summary>
        public static void Setup()
        {
            if (!_controlHostInitialized)
            {
                if (_trackingId != null)
                {
                    var popup = new Popup();
                    var hostControlInstance = new HostControl(_trackingId);
                    hostControlInstance.Initialized += RegisterGaJsControl;
                    popup.Child = hostControlInstance;
                    //popup.Child = new TextBlock() { Text = "sadasda", Foreground = new SolidColorBrush(Colors.Red) };
                    popup.Width = popup.Height = 1d;
                    popup.RenderTransform = new TranslateTransform() { X = -20, Y = -20 };
                    popup.IsOpen = true;
                    _controlHostInitialized = true;
                }
            }
        }

        #endregion
    }
}